package org.dromara.creditcard.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dromara.common.core.exception.TransactionalException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MathUtil;
import org.dromara.common.core.utils.OrderUtil;
import org.dromara.common.core.utils.RandomUtil;
import org.dromara.creditcard.domain.*;
import org.dromara.creditcard.mapper.*;
import org.dromara.creditcard.service.ICreditCardService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 信用卡列Service业务层处理
 *
 * @author Mr.Zhou
 * @date 2023-11-29
 */
@RequiredArgsConstructor
@Service
public class CreditCardServiceImpl extends ServiceImpl<CreditCardMapper, CreditCard> implements ICreditCardService {

    private final CreditCardMapper cardMapper;

    private final CreditHolderMapper holderMapper;

    private final CreditBillTemplateMapper billTemplateMapper;

    private final CreditMerMapper creditMerMapper;

    private final CreditOutRecordMapper outRecordMapper;

    private final CreditInRecordMapper inRecordMapper;

    private final CreditBillMonthRecordMapper billMonthRecordMapper;


    /**
     *  拆分账单
     * @param monthRecord
     * @param card
     * @return
     */
    @Override
    @Transactional
    public int splitBill(CreditBillMonthRecord monthRecord, CreditCard card) {
        int ret = 0;
        try{
            //拆分月份
            String monthStr = monthRecord.getMonthCode();
            //拆分类型  0 - 先进后出 1 - 先出后进
            int billType = monthRecord.getBillType();
            CreditBillTemplate billTemplate = billTemplateMapper.selectById(card.getBillTemplateId());
            CreditMer posMer = creditMerMapper.selectById(card.getPosMerId());
            CreditMer qrMer = creditMerMapper.selectById(card.getQrMerId());
            CreditHolder holder = holderMapper.selectById(card.getHolderId());
            String[] yearMonth = monthStr.split("-");

            //已生成月份标识的id
            int monthRecordId = monthRecord.getId();
            //信用卡总剩余额度
            double totalMoney = card.getLeftLimit().doubleValue();
            //本月拆分金额
            double billTotalMoney = monthRecord.getBillTotalMoney().doubleValue();

            //开启日期（账单日）
            String beginDate = monthRecord.getBeginDate();
            //结束日期（还款日）
            String endDate = monthRecord.getEndDate();

            Date repayDay = DateUtils.parseDate(endDate + " 23:59:59");
            //计算出 现在距离还款日还有多少天
            int days = DateUtils.differentDaysByMillisecond(new Date(), repayDay);
            System.out.println("现在距离还款日还有多少天: " + days);

            int totalCount = billTemplate.getPosOutCount() + billTemplate.getQrOutCount();
            //总出账时间集合
            List<Date> payDays = DateUtils.getDateListByCount(1,totalCount / 2);

            //分成2部分，前半部分是pos的  后半部分是 扫码的
            List<List<Date>> getSplitDate = DateUtils.getRandomListByList(payDays, billTemplate.getPosOutCount());
            //随机出来pos出账时间集合
            List<Date> posDays = getSplitDate.get(0);
            //随机出来扫码出账时间集合
            List<Date> qrDays = getSplitDate.get(1);
            ///////// 出账单 /////////////
            //pos 拆分账单
            try{
                int posRet = addOutPosRecord(monthRecordId, card, monthStr, holder,posMer, billTemplate, totalMoney, posDays,repayDay);
                monthRecord.setPosState(posRet);
            }catch (Exception e){
                monthRecord.setPosState(2);
            }
            //扫码 拆分账单
            try{
                int qrRet = addOutQrRecord(monthRecordId,card,monthStr,holder,qrMer,billTemplate, totalMoney, qrDays,repayDay);
                monthRecord.setQrState(qrRet);
            }catch (Exception e){
                monthRecord.setQrState(2);
            }

            ret = billMonthRecordMapper.updateById(monthRecord);
            if(ret < 0){
                throw new TransactionalException("billMonthRecordMapper updateById error");
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new TransactionalException("splitBill system error");
        }
        return ret;
    }

    /**
     *  拆分POS出账账单
     * @param card
     * @param monthStr
     * @param holder
     * @param billTemplate
     * @param totalMoney
     */
    @Transactional(rollbackFor = Exception.class)
    public int addOutPosRecord(int monthRecordId, CreditCard card, String monthStr, CreditHolder holder,
                               CreditMer posMer, CreditBillTemplate billTemplate, double totalMoney,
                               List<Date> payDays, Date repayDay){
        int ret = 0;
        try{
            //pos出账总次数
            int posOutCount = billTemplate.getPosOutCount();
            if(posOutCount > 0){
                //pos 出账比例
                double posOutTotal = billTemplate.getPosOutTotal().doubleValue();
                //pos费率
                double posStandardRate = posMer.getPosStandardRate().doubleValue();
                //pos费率
                double posRate = posMer.getPosRate().doubleValue();
                //pos 出账金额
                double posTotalMoney = MathUtil.getDoubleUp(totalMoney * posOutTotal / 100);
                //pos  拆分单笔最小数
                double posOutSingleMin = posTotalMoney * billTemplate.getPosOutSingleMin().doubleValue() / 100;
                //pos  拆分单笔最大数
                double posOutSingleMax = posTotalMoney * billTemplate.getPosOutSingleMax().doubleValue() / 100;
                //随机金额
//                List<Double> randomMoney = RandomUtil.randomDoubleByTotalAndCount(posTotalMoney, payDays.size(), posOutSingleMin, posOutSingleMax);

                List<Integer> randomMoney = RandomUtil.randomIntegerByTotalAndCount((int)posTotalMoney, payDays.size(), (int)posOutSingleMin, (int)posOutSingleMax);
                System.out.println("OutPosRecord : =" + randomMoney.toString());
                int index = 0;
                for (Integer money : randomMoney){
                    if(money == 0){
                        continue;
                    }
                    CreditOutRecord outRecord = new CreditOutRecord();
                    String recordNo = OrderUtil.getOrderNoByTime();
                    outRecord.setRecordNo(recordNo);
                    outRecord.setAgentId(card.getAgentId());
                    outRecord.setMonthRecordId(monthRecordId);
                    outRecord.setCardId(card.getId());
                    outRecord.setMonthDate(monthStr);
                    outRecord.setHolderName(holder.getRealName());
                    outRecord.setPhoneNum(holder.getPhoneNum());
                    outRecord.setCardNum(card.getCardNum());
                    outRecord.setHolderId(card.getHolderId());
                    outRecord.setRecordType(0);
                    outRecord.setPayMoney(new BigDecimal(0));//支付金额
                    outRecord.setBillMoney(new BigDecimal(money));//账单金额
                    outRecord.setPayRate(posMer.getPosRate());//还款费率
                    //本账单还款日期
                    outRecord.setBillOutDay(payDays.get(index));
                    //执行费率 手续费  当前还款金额 * 费率（实际扣除的）
                    double fee = MathUtil.getDoubleUp(money * posRate /100);
                    outRecord.setPayFee(new BigDecimal(fee));
                    //标准费率
                    outRecord.setManageRate(posMer.getPosStandardRate());
                    //标准费率的手续费（标准扣除的）
                    double manageFee = MathUtil.getDoubleUp(money * posStandardRate /100);
                    outRecord.setManageFee(new BigDecimal(manageFee));
                    //标准 - 执行 = 剩余利润
                    double profit = MathUtil.getDoubleUp(manageFee - fee);
                    outRecord.setProfit(new BigDecimal(profit));
                    //还款日
                    outRecord.setRepayDay(repayDay);
                    outRecord.setState(0);
                    outRecord.setIsQrPay(0);
                    outRecord.setIsDanger(0);
                    outRecord.setIsDel(0);
                    outRecord.setCreateTime(new Date());
                    ret = outRecordMapper.insert(outRecord);
                    if(ret <= 0){
                        throw new TransactionalException("outRecordMapper insert error");
                    }
                    index++;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            ret = 2;
            throw new TransactionalException("addOutPosRecord insert error");
        }
        return ret;
    }


    /**
     *  拆分扫码出账账单
     * @param card
     * @param monthStr
     * @param holder
     * @param billTemplate
     * @param totalMoney
     */
    @Transactional(rollbackFor = Exception.class)
    public int addOutQrRecord(int monthRecordId, CreditCard card, String monthStr, CreditHolder holder, CreditMer qrMer, CreditBillTemplate billTemplate, double totalMoney, List<Date> payDays, Date repayDay){
        int ret = 0;
        try{
            //扫码 出账总次数
            int qrOutCount = billTemplate.getQrOutCount();
            if(qrOutCount > 0){
                //扫码 出账比例
                double qrOutTotal = billTemplate.getQrOutTotal().doubleValue();
                //标准费率
                double qrStandardRate = qrMer.getQrStandardRate().doubleValue();
                //执行 扫码 费率
                double qrRate = qrMer.getQrRate().doubleValue();
                //扫码 出账金额
                double qrTotalMoney = MathUtil.getDoubleUp(totalMoney * qrOutTotal / 100);
                //扫码  拆分单笔最小数
                double qrOutSingleMin = qrTotalMoney *  billTemplate.getQrOutSingleMin().doubleValue() / 100;
                //扫码  拆分单笔最大数
                double qrOutSingleMax = qrTotalMoney *  billTemplate.getQrOutSingleMax().doubleValue() / 100;

                int index = 0;
                //随机金额
                List<Double> randomMoney = RandomUtil.randomDoubleByTotalAndCount(qrTotalMoney, payDays.size(), qrOutSingleMin, qrOutSingleMax);
                System.out.println("OutQrRecord : =" + randomMoney.toString());
                for (Double money : randomMoney){
                    if(money == 0){
                        continue;
                    }
                    CreditOutRecord outRecord = new CreditOutRecord();
                    String recordNo = OrderUtil.getOrderNoByTime();
                    outRecord.setRecordNo(recordNo);
                    outRecord.setAgentId(card.getAgentId());
                    outRecord.setMonthRecordId(monthRecordId);
                    outRecord.setCardId(card.getId());
                    outRecord.setMonthDate(monthStr);
                    outRecord.setHolderName(holder.getRealName());
                    outRecord.setPhoneNum(holder.getPhoneNum());
                    outRecord.setCardNum(card.getCardNum());
                    outRecord.setHolderId(card.getHolderId());
                    outRecord.setRecordType(0);
                    outRecord.setPayMoney(new BigDecimal(0));//支付金额
                    outRecord.setBillMoney(new BigDecimal(money));//账单金额
                    outRecord.setPayRate(qrMer.getQrRate());//还款费率
                    //账单出款日期
                    outRecord.setBillOutDay(payDays.get(index));
                    //手续费  当前还款金额 * 费率
                    double fee = MathUtil.getDoubleUp(money * qrRate /100);
                    outRecord.setPayFee(new BigDecimal(fee));
                    //标准费率
                    outRecord.setManageRate(qrMer.getQrStandardRate());
                    //标准费率的手续费（标准扣除的）
                    double manageFee = MathUtil.getDoubleUp(money * qrStandardRate /100);
                    outRecord.setManageFee(new BigDecimal(manageFee));
                    //标准 - 执行 = 剩余利润
                    double profit = MathUtil.getDoubleUp(manageFee - fee);
                    outRecord.setProfit(new BigDecimal(profit));
                    //还款日
                    outRecord.setRepayDay(repayDay);
                    outRecord.setState(0);
                    outRecord.setIsQrPay(1);
                    outRecord.setIsDanger(0);
                    outRecord.setIsDel(0);
                    outRecord.setCreateTime(new Date());
                    ret = outRecordMapper.insert(outRecord);
                    if(ret <= 0){
                        throw new TransactionalException("outRecordMapper insert error");
                    }
                    index ++;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            ret = 2;
            throw new TransactionalException("addOutQrRecord system error");
        }
        return ret;
    }


    /**
     *  拆分入账账单
     * @param card
     * @param monthStr
     * @param holder
     * @param billTemplate
     * @param totalMoney
     */
    private void addInRecord(int monthRecordId, CreditCard card, String monthStr,CreditHolder holder, CreditBillTemplate billTemplate, double totalMoney){

        //pos出账总次数
        int inCount = billTemplate.getInCount();
        if(inCount > 0){

            //pos  拆分单笔最小数
            double inSingleMin = billTemplate.getInSingleMin().doubleValue();
            //pos  拆分单笔最大数
            double inSingleMax = billTemplate.getInSingleMax().doubleValue();

            //pos 出账金额
            double posTotalMoney = 0;//MathUtil.getDoubleUp(totalMoney * posOutTotal / 100);


            //随机金额
            List<Double> randomMoney = RandomUtil.randomDoubleByTotalAndCount(posTotalMoney, inCount, inSingleMin, inSingleMax);
            for (Double money : randomMoney){

                CreditInRecord inRecord = new CreditInRecord();
                inRecord.setMonthRecordId(monthRecordId);
                inRecord.setCardId(card.getId());
                inRecord.setMonthDate(monthStr);
                inRecord.setHolderName(holder.getRealName());
                inRecord.setPhoneNum(holder.getPhoneNum());
                inRecord.setCardNum(card.getCardNum());
                inRecord.setHolderId(card.getHolderId());
                inRecord.setRecordType(0);
                inRecord.setRepayMoney(new BigDecimal(money));//预计入账金额
                inRecord.setPayMoney(new BigDecimal(money));//实际支付金额
                //还款日
//                inRecord.setRepayDay(card.getRepaymentDay());
//                //本账单还款日期
//                inRecord.setBillRepayDay(card.getRepaymentDay());
                inRecord.setState(0);

                inRecord.setIsDanger(0);
                inRecord.setIsDel(0);
                inRecord.setCreateTime(new Date());

                inRecordMapper.insert(inRecord);
            }
        }
    }

}
